package com.cqs.learning.spring.cloud.producer.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import lombok.extern.log4j.Log4j2;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lixw
 * @date 2020/3/24 14:28
 */
@Log4j2
@Service
public class ServiceDemoImpl implements ServiceDemo {

    private static final AtomicInteger cnt = new AtomicInteger(0);

    @Resource(name = "redisTemplate")
    private RedisTemplate<String, Integer> redisTemplate;

    @Override
    @SentinelResource(value = "fuseDemo", blockHandler = "fuseBlockHandler", fallback = "fuseFallback")
    public String fuseAndDegrade(int num) {
        return fuseAndDegrade0(num);
    }

    @Override
    @SentinelResource(value = "fuseDemo", blockHandler = "fuseBlockHandler", fallback = "fuseFallback")
    public String fuseAndDegrade2(int num) {
        return fuseAndDegrade0(num);
    }


    @SentinelResource(value = "cnt", blockHandler = "cntBlockHandler", fallback = "cntFallback")
    @Override
    public int cnt() {
        return cnt.addAndGet(1);
    }

    @Override
    public int cnt2() {
        int userId = new Random().nextInt(1 << 10);
        String key = "userId_" + userId;
        Integer cnt = redisTemplate.opsForValue().get(key);
        if (cnt == null) {
            cnt = 0;
        }
        log.info("用户登录次数:" + cnt);
        redisTemplate.opsForValue().set(key, ++cnt);
        return cnt;
    }

    @Override
    public int flowAuthority(String origin) {
        log.info("请求源是{}", origin);
        return new Random().nextInt(1000);
    }


    public String fuseAndDegrade0(int num) {
        if (num <= 0) {
            //模拟异常
            throw new IllegalArgumentException("不合法的参数");
        }
        if (num < 10) {
            //模拟显示超时
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "计算结果:" + (num << 1);
    }

    /***
     * 熔断或者限流的时候执行
     * 或者抛出异常逻辑
     * @param num
     * @param throwable
     * @return
     */
    public String fuseFallback(int num, Throwable throwable) {
        log.warn(throwable.getClass() + " 执行fuseFallbackk:" + num);
        return "执行fuseFallback:" + num;
    }

    public String cntFallback(Throwable throwable) {
        log.warn(throwable.getClass() + " 执行cntFallback:");
        return "执行cntFallback";
    }

    /**
     * 异常处理
     *
     * @param num
     * @param ex
     * @return
     */
    public static String fuseBlockHandler(int num, Throwable ex) {
        log.warn("执行blockHandler:" + num + "\t" + ex.getMessage());
        return "执行blockHandler:" + num + "\t" + ex.getMessage();
    }

    /**
     * 异常处理
     *
     * @param ex
     * @return
     */
    public static String cntBlockHandler(Throwable ex) {
        log.warn("执行cntBlockHandlerr:" + "\t" + ex.getMessage());
        return "执行cntBlockHandler:" + "\t" + ex.getMessage();
    }


}
